﻿#region MIT Licenze
//The MIT License

//Copyright (c) 2008 Sebastian Faltoni, dotnetfireball.org

//Permission is hereby granted, free of charge, to any person obtaining a copy
//of this software and associated documentation files (the "Software"), to deal
//in the Software without restriction, including without limitation the rights
//to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
//copies of the Software, and to permit persons to whom the Software is
//furnished to do so, subject to the following conditions:

//The above copyright notice and this permission notice shall be included in
//all copies or substantial portions of the Software.

//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
//IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
//FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
//AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
//LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
//OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
//THE SOFTWARE.
#endregion
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Packaging;
using System.IO;
using System.Xml.Linq;

namespace Fireball.ImagePak
{
    public class ImagePackage
    {
        private ZipPackage _ZipPackage = null;
        private PackagePart _PackageInfoPart = null;

        internal ImagePackage(Stream strm)
        {
            _ZipPackage = (ZipPackage)ZipPackage.Open(strm, FileMode.OpenOrCreate);
            _Datas = new ImageCollection(this);
            Load();
        }

        public static ImagePackage Open(string filename)
        {
            return new ImagePackage(File.Open(filename, 
                FileMode.Open));
        }

        public static ImagePackage Create(string filename)
        {
            return new ImagePackage(File.Open(filename, 
                FileMode.Create ));
        }

        internal ZipPackagePart CreatePackagePart(Uri uri, string contentType)
        {
            return (ZipPackagePart)_ZipPackage.CreatePart(uri, contentType);
        }

        private ImageCollection _Datas = null;

        public ImageCollection Datas
        {
            get
            {                
                return _Datas;
            }
        }

        private ImagePackageInfo _PackageInfo = null;

        public ImagePackageInfo PackageInfo
        {
            get
            {
                return _PackageInfo;
            }
        }

        private bool loaded = false;
        private void Load()
        {
            if (loaded)
                return;
            var allParts = _ZipPackage.GetParts();

            var parts = from ZipPackagePart p in allParts
                        where p.Uri.OriginalString.StartsWith("/Images/Data/") == true
                        select p;

            foreach (var part in parts)
            {
                this.Datas.AddImageFromPackagePart(part);
            }

            var pkUri = new Uri("/PackageInfo/info.xml", UriKind.Relative);

            PackagePart pkInfo = _ZipPackage.PartExists(pkUri) ? _ZipPackage.GetPart(pkUri) : null;

            if (pkInfo == null)
            {
                this._PackageInfo = new ImagePackageInfo();
                this.PackageInfo.MainImage = new Uri("/Images/Data/" + Guid.NewGuid().ToString() + ".bin",UriKind.Relative);

                var p = _ZipPackage.CreatePart(pkUri, "text/xml", CompressionOption.Maximum);
                this.PackageInfo.ToXml().Save(new StreamWriter(p.GetStream()));
                this._PackageInfoPart = p;
            }
            else
            {
                XElement xEl = XElement.Load(new StreamReader(pkInfo.GetStream()));

                this._PackageInfo = ImagePackageInfo.Parse(xEl);
                this._PackageInfoPart = pkInfo;
            }


        }

        private void StorePkInfo()
        {
            var pkInfo = _ZipPackage.GetPart(
                new Uri("/PackageInfo/info.xml", UriKind.Relative));

            this.PackageInfo.ToXml().Save(
                new StreamWriter(pkInfo.GetStream()));
        }

        public void Close()
        {
            StorePkInfo();
            _ZipPackage.Flush();
            _ZipPackage.Close();
        }
    }
}
